home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
t3_1
/
doc.lha
/
documentation
/
manual
/
debug.mss
< prev
next >
Wrap
Text File
|
1987-06-30
|
18KB
|
452 lines
@part[Debug, root "TMAN.MSS"] @Comment{-*-System:TMAN-*-}
@chap[Debugging]
@label[debugging chapter] @comment{Referred to from user interface chapter.}
The facilities described in this chapter are highly
implementation-specific, and subject to change without notice.
Facilities described here are intended either for use directly as
commands, or as utilities for user-written debugging subsystems.
@section[Errors]
@index[Errors]
@label[Errors Interface Section] @Comment{ref: Errors Section}
@label[dealing section]
When the implementation detects an error condition, a message is printed and
a read-eval-print loop is entered in the dynamic context in which
the error occurred. A number of facilities are available at this
point for debugging and for recovering from the error.
Errors are usually detected in conditions which are left
undefined by the manual (see sections @ref[undefined semantics section]
and @ref[errors section]). These conditions include the following:
@itemize[
An unbound variable is referenced.
A procedure is called with too few or too many arguments.
A non-procedure is called.
An object of the wrong type is passed to a system procedure.
A string or vector index is out of range.
A generic operation is invoked on an object with no method
to handle it.
The external representation of an object being parsed by @tc[READ-OBJECT]
or a read macro is syntactically incorrect. (This kind of error
is called a @i[read error.])
An object being interpreted as an expression by a compiler or a
macro expander is syntactically incorrect. (This kind of error is
called a @i[syntax error.])
A call to @tc[ERROR] or @tc[UNDEFINED-EFFECT] occurs.
]
Once inside the read-eval-print loop, one may examine the current
environment (e.g., examining variables or the stack) using the
read-eval-print loop (section @ref[REPL section]) or the inspector
(section @ref[inspector section]).
Typical actions after an error occurs include:
@begin[itemize]
The user corrects the error by returning a new value
with @tc[RET].
The user goes up one command level by typing the end-of-file character
(see page @pageref[end-of-file]).
The user throws to top level by calling @tc[(RESET)] (page @pageref[RESET]).
@end[itemize]
Example:
@begin[ProgramExample]
> (CADR 3)
** Error: attempting to take CADR of 3
>> (RET '(A B))
B
> (PLUS 3 4)
** Error: variable PLUS has no value
>> (RET ADD)
7
@end[ProgramExample]
@dc[Talk about errors from compiled code.]
@info[notes="Settable"]
@desc[(RECKLESSNESS) @yl[] LOW, MEDIUM, @r[or] HIGH]
Doing @tc[(SET (RECKLESSNESS) 'HIGH)] will improve performance at
the expense of error-checking. Specifically, somewhere between 10
and 25 instructions will be elided from most procedure calls, but
wrong-number-of-argument, undefined-procedure, and object-not-applicable
errors will probably cause illegal memory references or odd address
errors instead of more comprehensible error reports.
@EndDesc[RECKLESSNESS]
@section[Debugging utilities]
@info[NOTES="Special form"]
@desc[(TRACE @i[variable]) @yl[] @i[undefined]]
Reassigns @i[variable], whose value should be a procedure,
to be a new procedure which prints information on the
@tc[(DEBUG-OUTPUT)] stream whenever it is called or returns a value.
@EndDesc[TRACE]
@info[NOTES="Special form"]
@desc[(UNTRACE @i[variable]) @yl[] @i[undefined]]
If @i[variable] has a traced procedure as its value,
@tc[UNTRACE] restores it to its original value.
Otherwise it prints a warning and does nothing.
@EndDesc[UNTRACE]
@info[NOTES="Special form"]
@desc[(PP @i[procedure]) @yl[] @i[undefined]]
Prints the definition of @i[procedure] on the terminal output stream.
If the source code is not available, then it prints the name of a file
where it can be found.
(See also @tc[PRETTY-PRINT], page @pageref[PRETTY-PRINT],
and @tc[WHERE-DEFINED], page @pageref[WHERE-DEFINED].)
@EndDesc[PP]
@desc[(BACKTRACE) @yl[] @i[undefined]]
Prints a one-line summary describing each continuation on the stack.
@index[continuations]
See also @tc[DEBUG], page @pageref[DEBUG].
@EndDesc[BACKTRACE]
@section[The inspector]
@label[inspector section]
@tc[CRAWL], also known as the @iix[inspector],
is a stack and structure inspector.
It consists of a command loop and a set of commands.
The inspector keeps track of a @i[current object], and a stack of
objects which have previously been current objects. Some inspector
commands move from one object to another.
The command loop operates as follows: the current object is
@qu"summarized" (that is, printed or displayed somehow); a prompt is
printed; a line is read; and any commands on the line are executed.
One can give one or more commands on a single input line.
The current object may be any object. If it is a continuation (stack frame),
the name of the procedure which contains the continuation's return point
is printed, and the prompt is @qu"@tc[debug:]". Otherwise, the object
is printed (up to a maximum of one line of output),
and the prompt is @qu"@tc[crawl:]".
@index[stack]
@index[frames]
@index[continuations]
The meanings of some commands vary depending on what kind of object
the current object is, and not all commands are
appropriate for all kinds of objects.
@desc[(DEBUG) @yl[] @i[undefined]]
@tc[(DEBUG)] enters the inspector. The current object becomes a continuation
near the top of the stack (more precisely, the continuation to which
the value passed to @tc[RET] will be given).
@EndDesc[DEBUG]
@desc[(CRAWL @i[object]) @yl[] @i[undefined]]
Enters the inspector. The current object becomes @i[object].
@EndDesc[CRAWL]
Inspector commands:
@begin[Description]
@tc[?]@\@i[Help:] prints a list of inspector commands, with one-line
summaries.
@tc[Q]@\@i[Quit:] exits out of the inspector, usually back to the
read-eval-print loop.
@tc[U]@\@i[Up:] pops the stack of saved objects. The current object is
forgotten, and the inspector moves to the previous current object.
@tc[D]@\@i[Down:] if the current object is a continuation,
moves to the next continuation deeper in the stack, that is, to the
continuation that
was pushed prior to the current continuation.
@begin[multiple]
@tc[X]@\@i[Exhibit:] prints useful information about the current object.
The exact behavior of this varies depending on the type of the object.
For structures, all of the structure's components are displayed.
For continuations, any saved values are printed. Integers are printed
in various radices.
For some kinds of object, such as structures and vectors, the contents
of an object will be displayed in a menu form, as a sequence of lines of
the form
@w[@qu"@tc<[@i[key]] @i[component]>"].
In this case, giving @i[key] as an inspector command will move to
@i[component], which then becomes the current object.
@end[multiple]
@i[integer]@\@i[Select element:] in the case of a list or vector,
this moves to the appropriate component. For example, if the current object
is a list, then @tc[3] as an inspector command is the same as @tc[A CADDDR]:
it moves to the list's fourth element.
@i[selector]@\@i[Select component:] if the current object is a structure,
typing a selector name will move to that component of the structure.
@tc[B]@\@i[Breakpoint:] enters a read-eval-print loop. Executing
@tc[(RET)] will return back into the inspector. The read-eval-print
loop will execute either in @tc[(REPL-ENV)], or, if the current object
is a continuation or procedure created by interpreted code (i.e. code
compiled by the standard compiler, as opposed to TC), in the lexical
environment of the object. Inside the breakpoint loop, the system
variable @tc[*OBJ*] is bound to the current object.
@tc[C]@\@i[Crawl:] moves to a new object. The
object is obtained by evaluating an input expression, which is
read either from the command line or in response to a prompt.
The environment of the evaluation is one appropriate to
the current object, as with the @tc[B] command.
@tc[E]@\@i[Evaluate:] evaluates an expression. The expression is read
and evaluated as
with the @tc[C] command. The result of the evaluation is printed, but
the current object remains the same.
@tc[A]@\@i[Apply:] applies a procedure to the current object, and move to the
result of that call. An expression evaluating to the procedure is
read as with the @tc[C] command.
@tc[M]@\@i[Macroexpand:] performs one macro expansion on the current
object, which should be a list, and the current object becomes the result
of the macro expansion.
@index[Macros]
@tc[P]@\@i[Pretty-print:] prints the current object using the pretty
printer.
If the current object is a continuation, then this command tries to
print the expression to which the value returned by the continuation
is to be supplied.
@tc[R]@\@i[Return:] if the current object is a continuation, returns a
value to it. The value is obtained as with the @tc[C],
@tc[E], and @tc[A] commands.
@comment{ not implemented in 2.7.
@tc[R]@\@i[Right:] if the current object is a list, this is the same
as @tc[A CDR]: that is, it moves to the list's cdr.
}
@tc[W]@\@i[Where-defined:] prints the result of calling @tc[WHERE-DEFINED]
on the current object.
@tc[V]@\@i[Unit:] moves to a template's or procedure's
unit. Units are not documented, but the @tc[X] command works with them.
This command is intended primarily for the use of the @Timp[] implementors.
@end[Description]
The control stack which one inspects by invoking the
inspector with @tc[(DEBUG)] is a sequence of continuations, or stack
frames. These differ from activation records in implementations of
languages such as C or Lisp in that they represent future computations
rather than past calls. A full call history is not easily
available in tail-recursive languages such a @Tau[] and Scheme.
This is implementation-dependent, of course, and future @Tau[]
implementations may maintain call histories for debugging purposes.
Each continuation represents a control point which will make use of
the value returned to the continuation. Usually these control points
correspond to the arguments in a call, the predicate in an @tc[IF]
or @tc[COND], or any but the last subform of a block. For example,
when evaluating a call, a continuation is constructed for each argument
in the call, because these values will be used when the call actually
occurs. In the example below, the continuations into @tc[FACT] were
mostly delivering values to the second argument position in the call
to @tc[*].
The three-column synopsis that the inspector prints for continuations
is the same as that printed by @tc[BACKTRACE] (page
@pageref[BACKTRACE]). The first column is the name of the procedure
into which control will return, or @tc[(anonymous)] if no procedure
name is available (as for procedures created by anonymous top-level
@tc[LAMBDA]-expressions instead of by @tc[DEFINE]). The second column
is the name of the source file containing the procedure, and the third
column is relevant source code, if available.
Here is a sample interaction with the inspector.
Commentary is in Roman font on the right.
The terms @qu"frame," @qu"stack frame," and @qu"continuation" are
used interchangeably.
@begin[ProgramExample]
> (define (fact n) @r[Define factorial function.]
(cond ((= n 0) i) @r[Bug: @tc[i] instead of @tc[1].]
(else (* n (fact (- n 1))))))
#{Procedure 120 FACT}
> (fact 4)
** Error: variable I is unbound @r[Error detected by interpreter.]
>> (debug)
#{Continuation 121} @r[Current object is this frame.]
BIND-INTERNAL THROW @r[Internal to the implementation.]
debug: d @r[Go down one frame.]
#{Dynamic-state-transition 122} @r[Also internal, keep going.]
debug: d
#{Continuation 123}
FACT () I @r[Okay, this looks good.]
debug: d
#{Continuation 124}
FACT () (* N (FACT (- N 1)))
debug: e n @r[Evaluate @tc[N] in this frame.]
1 @r[Value is 1.]
debug: d
#{Continuation 125}
FACT () (* N (FACT (- N 1)))
debug: e n @r[Value is 2 in this frame.]
2
debug: d d @r[Go down two frames.]
#{Continuation 126}
FACT () (* N (FACT (- N 1)))
debug: d
#{Continuation 127}
READ-EVAL-PRINT-LOOP REPL @r[@tc[FACT]'s caller (i.e. top level).]
debug: u u u u u @r[Up five frames.]
#{Continuation 123}
FACT () I
debug: r 1 @r[Return the value 1 to this frame.]
24 @r[Execution proceeds, and the value]
> @r[24 comes out.]
@end[ProgramExample]
@section[Debugging primitives]
This section describes routines which may be useful in writing debugging
aids. Note that they are not part of the language, and therefore should be
avoided in @qu"ordinary" programs. Relying on these routines may lead
to programs which behave differently depending on how the programs
are compiled (TC or standard compiler), or which fail to work
across releases.
@info[NOTES="Operation"]
@desc[(WHERE-DEFINED @i[object]) @yl[] @i[filename]]
Tries to find a filename for the source file wherein
@i[object] (usually a procedure) is defined.
@EndDesc[WHERE-DEFINED]
@info[NOTES="Operation"]
@desc[(IDENTIFICATION @i[object]) @yl[] @i[symbol] @r[or] @i[false]]
If appropriate, this returns a symbol naming a variable which, in some
environment, might be defined to be the @i[object]. If no such
identification is appropriate, @tc[IDENTIFICATION] returns false. This
behavior is heuristic, not contractual; for no value is @tc[IDENTIFICATION]
required to return non-null.
@begin[ProgramExample]
(IDENTIFICATION CADR) @ev[] CADR
(LET ((X CADR)) (IDENTIFICATION X)) @ev[] CADR
@end[ProgramExample]
@EndDesc[IDENTIFICATION]
@info[NOTES="Operation"]
@desc[(ARGSPECTRUM @i[procedure]) @yl[] @i[pair]]
Returns an @i[argspectrum] for @i[procedure]. An argspectrum is a pair
@wt[(@i[min] . @i[max])] which describes the number of arguments that
@i[procedure] expects to receive when called. @i[Min] is always an
integer giving the minimum number of arguments expected; @i[max] is
either an integer giving a maximum, or it is @tc[()], meaning that exactly
@i[min] arguments are required, or it is @tc[T], meaning that any number
of arguments (but at least @i[min]) are acceptable. @dc[This convention
seems pretty random; suggest something better.]
@EndDesc[ARGSPECTRUM]
@desc[(DISCLOSE @i[procedure]) @yl[] @i[list] @r[or] @i[false]]
Attempts to reconstruct a source expression from which @i[procedure]
may have been compiled. This may work for code compiled using the
standard compiler, but is likely to fail to work for code compiled using
TC. Returns false if no source code can be obtained.
@EndDesc[DISCLOSE]
@desc[(GET-ENVIRONMENT @i[procedure]) @yl[] @i[environment] @r[or] @i[false]]
Attempts to reconstruct an environment in which @i[procedure]
may have been loaded (or run). This may work for code compiled using the
standard compiler, but is likely to fail to work for code compiled using
TC. Returns false if no environment can be obtained.
@EndDesc[GET-ENVIRONMENT]
@desc[(STRUCTURE-TYPE @i[object]) @yl[] @i[stype] @r[or] @i[false]]
If @i[object] is a structure, this returns the structure type of which
it is an instance. If @i[object] is not a structure, it returns false.
@tc[STRUCTURE-TYPE] is to be used with care since it may violate the
data protection otherwise provided by structure types. That is, anyone
who is given a structure may find out about its internals.
@EndDesc[STRUCTURE-TYPE]
@info[EQUIV="MAPATOMS"]
@desc[(WALK-SYMBOLS @i[procedure]) @yl[] @i[undefined]]
Calls @i[procedure] on every accessible symbol.
@EndDesc[WALK-SYMBOLS]
@section[Miscellaneous]
@desc[*T-VERSION-NUMBER* @yl[] @i[integer]]
An integer which gives the version number of the currently running @Tau[]
implementation.
The integer has the form
@begin[ProgramExample]
(+ (* @i[major-version-number] 1000) @i[minor-version-number])
@end[ProgramExample]
For example, in @Timp[] 2.7, @tc[*T-VERSION-NUMBER*] is @tc[2007]. Knowledge
of the version number may be useful in dealing with
incompatibilities between @Timp[] releases, so that programs may
conditionally adjust their state according to the version, and thus
be able to run in both older and newer releases.
@enddesc[*T-VERSION-NUMBER*]
@desc[*T-IMPLEMENTATION-ENV* @yl[] @i[locale]]
This environment contains variables internal to the implementation of
@Tau[].
@begin[ProgramExample]
(IMPORT *T-IMPLEMENTATION-ENV* %%PAIR-TAG)
@end[ProgramExample]
@enddesc[*T-IMPLEMENTATION-ENV*]
@desc[*TC-ENV* @yl[] @i[locale]]
This environment contains variables internal to the implementation
of TC.
@EndDesc[*TC-ENV*]
@desc[(GC) @yl[] @i[undefined]]
Invokes the garbage collector.@index[Garbage collection]
Garbage collection is a low-level process by which the memory used by
objects which are no longer accessible is reclaimed for use by new
objects.
Ordinarily, garbage collection is invoked asynchronously as the need
arises, so explicit calls to @tc[GC] are unnecessary.
A side-effect of garbage collection is that any streams created by
@tc[OPEN] which are both inaccessible and still open, are closed.
See also section @ref[OBJECT-HASH].
@EndDesc[GC]
@desc[(GC-STATS) @yl[] @i[undefined]]
Prints some statistics about the most recent garbage collection.
@EndDesc[GC-STATS]
@info[NOTES="Settable"]
@desc[(GC-NOISILY?) @yl[] @i[boolean]]
Switch, initially true. If true, then the garbage collector will print
messages when invoked. If false, it will do its work silently.
@EndDesc[GC-NOISILY?]